// Copyright (c) 2025, 大连理工大学 (Dalian University of Technology)
//
// Licensed under the Mulan PSL v2.
// You can use this file according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of the License at
//
//     http://license.coscl.org.cn/MulanPSL2
//
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. SEE THE MULAN PSL v2
// FOR MORE DETAILS.

#include "BDFImport.h"

#include <algorithm>
// c++
#include <cstddef>
#include <exception>
#include <fstream>
#include <ios>
#include <memory>
#include <set>
#include <string>
#include <vector>

#include <boost/algorithm/string.hpp>
#include <boost/filesystem.hpp>

#include "Utility/Exception/SGException.h"
#include "Utility/FileSystem/SGFileSystem.h"
#include "Utility/Logging/SGLogger.h"

#include "DataStructure/Input/Constraint/GRDSETData.h"
#include "DataStructure/Input/Solver/Subcase.h"

#include "DBManager/DBServiceFactory.h"
#include "DBManager/IService/Input/Load/ILSEQService.h"
#include "DBManager/IService/Input/Parameter/IParameterService.h"
#include "DBManager/IService/Input/Parameter/ISETSService.h"
#include "DBManager/IService/Input/Subcase/IInputDomainsService.h"
#include "DBManager/IService/Input/Subcase/ISubcaseService.h"

#include "Import/BDFImport/BulkData/BulkDataEntryParserFactory.h"
#include "Import/BDFImport/ControlData/CaseDataEntryParserFactory.h"

#include "BDFParserBase.h"

SG_IMPORT_BDF_NAMESPACE_OPEN

/**
 * \defgroup 全局解析参数
 *  一些全局的解析参数
 * @{
 */

/**
 * @brief    GRID默认数据
 *  如果GRID条目中的坐标系ID、位移输出坐标系、约束为空，则此条目定义的默认选项将出现在该字段中。
 *  BulkData中只能出现一个GRDSET 条目。
 * @todo 在官方文档中的remark中的第一条的后半句没有进行处理~
 * @author   wuxingchuang
 * @date     2025.02.05
 */
SG::DataStructure::FEM::GRDSETData* g_grdset = nullptr;

/**
 * @brief    以ENDT为结尾的词条
 * e.g.:
 * TABLED1     1000
 * +            1.0     1.0   200.0     1.0    ENDT
 *
 * @author   wuxingchuang
 * @date     2025.03.31
 */
static std::set<std::string> s_endtEntry = { "TABLED1", "TABDMP1" };

/**
 *@}
 */
SG_IMPORT_BDF_NAMESPACE_CLOSE

using namespace std;
using namespace boost::algorithm;
using namespace boost::filesystem;
using namespace boost;
using namespace SG::Import;
using namespace SG::Import::BDF;
using namespace SG::DBManager;
using namespace SG::DataStructure;
using namespace SG::Utility;

BDFImporter::BDFImporter (const std::shared_ptr<SG::DBManager::DBServiceFactory>& dbServiceFactory)
{
    m_dbServiceFactory = dbServiceFactory;
    m_CompleteLine.reserve (500);
}

BDFImporter::~BDFImporter ()
{
    // 每此导入都需要使用新的参数
    if (g_grdset != nullptr)
    {
        delete g_grdset;
        g_grdset = nullptr;
    }
};

#ifdef CARD_EXTRACT
#include <iostream>
namespace CardExtractor
{
    enum cardtype : std::uint8_t
    {
        CARD_TYPE_CONTROL,                                              ///< Control Data类型
        CARD_TYPE_PARAM,                                                ///< Case Data类型
        CARD_TYPE_BULK,                                                 ///< Bulk Data类型
        CARD_TYPE_UNSUPORT                                              ///< 未知类型
    };

    static std::map<cardtype, std::set<std::string>> s_CardExtractMap;  ///< 用于存储提取的卡片数据

    static void addCard (const cardtype type, const std::string card)
    {
        if (s_CardExtractMap.find (type) == s_CardExtractMap.end ())
        {
            s_CardExtractMap[type] = std::set<std::string> ();
        }
        s_CardExtractMap[type].insert (card);
    }

    static void printCard ()
    {
        for (const auto& [type, cards] : s_CardExtractMap)
        {
            if (cards.empty ())
            {
                continue;  // 如果没有卡片数据，跳过
            }
            switch (type)
            {
            case CARD_TYPE_BULK:
                std::cout << "Bulk Cards:" << "\n";
                break;
            case CARD_TYPE_CONTROL:
                std::cout << "Control Cards:" << "\n";
                break;
            case CARD_TYPE_PARAM:
                std::cout << "Param Cards:" << "\n";
                break;
            default:
                std::cout << "DLUTFEM Unsuport Cards:" << "\n";
                break;
            }
            // 每4个card一行，每个card占用16位
            for (const auto& card : cards)
            {
                std::cout << std::setw (20) << card;
                if ((std::distance (cards.begin (), cards.find (card)) + 1) % 3 == 0 && cards.find (card) != std::prev (cards.end ()))
                {
                    std::cout << "\n";  // 每4个card换行
                }
            }
            std::cout << "\n\n";
        }
    }

}  // namespace CardExtractor

#endif

Common::Status BDFImporter::Load (const char* szfile)
{
    SG::Import::BDF::CaseDataEntryParserFactory::GetInstance ()->ClearField ();

    // 记录函数进入日志，并输出传入的文件名参数
    SGInfo << "Begin Import file : " << szfile;
    // 尝试以只读模式打开输入文件
    std::ifstream BDFFile (szfile, ios::in);
    if (!BDFFile.is_open ())
    {
        // 如果文件无法打开，记录错误日志并返回 false
        SGError << "[Function: BDFImport::Load] Unable to open input file: '" << szfile << "'";
        return Common::Status::STATUS_Failure;
    }

    std::queue<std::string> linesQueue;  // 创建一个队列用于存储读取的行
    std::string             line;
    while (std::getline (BDFFile, line))
    {
        linesQueue.push (line);
    }
    // 关闭文件
    BDFFile.close ();
    // 更新m_foldPath与m_fileName
    FileSystem::extractDirectoryAndFileName (szfile, m_foldPath, m_fileName);

    // 调用 ParseFileWithStack 函数进行文件解析，并检查解析是否成功
    const bool isSuc = ParseFile ({ m_foldPath }, linesQueue);
    if (!isSuc)
    {
        // 如果文件解析失败，记录错误日志并返回 false
        SGError << "[Function: BDFImport::Load] ParseFile failed";
        return Common::Status::STATUS_Failure;
    }

    // 调用 ParseControl 函数进一步处理
    if (!ParsePostBlock ())
    {
        return Common::Status::STATUS_Failure;
    }

    // 生成DOMAINS
    // to do 多module编号确定
    FEM::InputDomains Domains = {
        1, 0, 0, 0, 0,
    };
    m_dbServiceFactory->get<IInputDomainsService> ()->Add (Domains);
    m_dbServiceFactory->get<IInputDomainsService> ()->Size ();

    // 使用 SGLog 输出 m_PostBlock 中未解析的文本块
#define unitTest
#ifdef unitTest
    SGTrace << "[Function: BDFImport::Load] donot parse text:";
    for (const std::string& entry : m_PostBlock)
    {
        SGTrace << entry;
    }
#else
    // 将未解析的词条输出到文件中
    // 使用与单元测试中bdf检测
    std::string filename = "output.txt";

    // 以追加模式打开文件
    std::ofstream file;
    file.open (filename, std::ios::app);  // ios::app 表示追加模式

    // 检查文件是否成功打开
    if (!file.is_open ())
    {
        std::cerr << "无法打开文件: " << filename << std::endl;
        return Common::Status::STATUS_Failure;
    }
    file << szfile << " : donot parse text\n";
    for (const std::string& entry : m_PostBlock)
    {
        file << entry << "\n";
    }

    // 关闭文件
    file.close ();
#endif

#ifdef CARD_EXTRACT
    bool startbulk = false;
    for (std::string& entry : m_PostBlock)
    {
        if (!entry.empty () && starts_with (trim_copy (entry), "BEGIN BULK"))
        {
            startbulk = true;
            continue;  // 如果是BEGIN BULK，跳过此行
        }
        if (starts_with (trim_copy (entry), "ENDDATA") || starts_with (trim_copy (entry), "CEND") || starts_with (trim_copy (entry), "SOL"))
        {
            continue;
        }
        if (!startbulk)
        {
            UpdateControlKey (entry);
            CardExtractor::addCard (CardExtractor::CARD_TYPE_CONTROL, m_ControlKey);
            CardExtractor::addCard (CardExtractor::CARD_TYPE_UNSUPORT, m_ControlKey);
        }
        else
        {
            UpdateCompleteLineKey (entry);
            CardExtractor::addCard (CardExtractor::CARD_TYPE_BULK, m_CompleteLineKey);
            CardExtractor::addCard (CardExtractor::CARD_TYPE_UNSUPORT, m_CompleteLineKey);
        }
    }
    CardExtractor::printCard ();
#endif

    // 返回 true，表示文件加载和解析成功
    return Common::Status::STATUS_Success;
}

bool BDFImporter::ParseFile (std::vector<std::string> folderStack, std::queue<std::string>& iFile)
{
    try
    {
        // 想要获取完整行，总要先获取到下一行才能进行判断是否已经获取完整，
        // GetCompleteLine函数先将curLine 加入到完整行vector中，因此先调用GetNextLine
        std::vector<std::string> dividedEntryInfo;
        dividedEntryInfo.reserve (500);
        std::string curLine;           // 定义一个用于存储当前行的字符串

        GetNextLine (iFile, curLine);  // 读取文件的下一行

        while (!curLine.empty ())      // break if error or eof
        {
            // 空行或者注释
            while (is_all_space (curLine) || starts_with (trim_left_copy (curLine), "$"))
            {
                GetNextLine (iFile, curLine);  // 如果是空行或注释，继续读取下一行
                if (curLine.empty ())
                {
                    return true;
                }
            }

            GetCompleteLine (iFile, curLine);

            // 从BulkData工厂获取解析函数
            auto pNEParse = BDF::BulkDataEntryParserFactory::GetInstance ()->GetFunction (m_CompleteLineKey);

            // 如果没有找到对应的解析函数
            if (nullptr == pNEParse)
            {
                // 可能是include
                const IncludeState res = ParseInclude (folderStack);
                switch (res)
                {
                case INCLUDE_FAIL:  // include 解析失败
                    return false;
                    break;
                case NOT_INCLUDE:   // 非include 将完整行存入 m_PostBlock
                    if ("PARAM" == m_CompleteLineKey)
                    {
                        m_ParameterBlock.insert (m_ParameterBlock.end (), m_CompleteLine.begin (), m_CompleteLine.end ());
                    }
                    else if ("NASTRAN" == m_CompleteLineKey)
                    {
                        m_ExecutiveSystemParameterBlock.insert (
                            m_ExecutiveSystemParameterBlock.end (), m_CompleteLine.begin (), m_CompleteLine.end ());
                    }
                    else
                    {
                        m_PostBlock.insert (m_PostBlock.end (), m_CompleteLine.begin (), m_CompleteLine.end ());
                    }
                    break;
                default:
                    break;
                }
            }
            // 如果找到对应的解析函数
            else
            {
                // 是否是BulkData，是则解析，不是 将完整行存入 m_PostBlock

                if (IsBulkDataLine ())
                {
#ifdef CARD_EXTRACT
                    // 如果是BulkData，且开启了CARD_EXTRACT宏
                    CardExtractor::addCard (CardExtractor::CARD_TYPE_BULK, m_CompleteLineKey);
#endif
                    BDF::divideBulkEntry (m_CompleteLine, dividedEntryInfo);
                    pNEParse (m_dbServiceFactory, dividedEntryInfo);
                }
                else
                {
                    m_PostBlock.insert (m_PostBlock.end (), m_CompleteLine.begin (), m_CompleteLine.end ());
                }
            }
        }
    }
    catch (const std::exception& e)
    {
        // 错误处理：记录异常信息并打印错误
        SGError << "[Function: BULKDATA::" << m_CompleteLineKey << "An error occurred";
        SGError << "Parse Line:";

        // 打印出所有的条目信息以便调试
        for (const auto& i : m_CompleteLine)
        {
            SGError << i;
        }

        return false;
    }
    catch (const SG::Utility::ParserError& e)
    {
        // 错误处理：记录异常信息并打印错误
        SGError << "[Function: BULKDATA::" << m_CompleteLineKey << "An error occurred";
        SGError << "Parse Line:";

        // 打印出所有的条目信息以便调试
        for (const auto& i : m_CompleteLine)
        {
            SGError << i;
        }

        return false;
    }

    return true;
}

bool BDFImporter::ParsePostBlock ()
{
    // 将postBlock中的Case内容进行解析
    ParseCaseControl ();
    ParseParameter ();
    ParseExecutiveSystemParameter ();

    // TODO(wxc) 后续考虑工况有自己单独的Set
    // 暂时对Set集合进行合并 对每个工况都复制相同的Set
    {
        auto setService     = m_dbServiceFactory->get<ISETSService> ();
        auto subcaseService = m_dbServiceFactory->get<ISubcaseService> ();

        vector<SG::DataStructure::FEM::SETSData> sets;
        setService->FindBySId (-1, sets);
        for (auto&& i : sets)
        {
            for (auto&& sid : subcaseService->GetAllSubcaseID ())
            {
                i.m_sId = sid;
                setService->Add (i);
            }
        }
    }

    return CheckLegalityLSEQ ();
}

bool BDFImporter::ParseParameter ()
{
    SG::Utility::SGParameter p;

    for (auto& para : m_ParameterBlock)
    {
        SG::Utility::SGParameter child;

        auto Vstr = BDF::divideFreeForm (para);
        switch (Vstr.size ())
        {
        case 3:
            p.AddString (Vstr[1], Vstr[2]);
            break;
        case 4:
            child.AddString ("V1", Vstr[2]);
            child.AddString ("V2", Vstr[3]);
            p.AddValue (Vstr[1], child);
            break;
        default:
            SGError << para << " Pares error";
            break;
        }

#ifdef CARD_EXTRACT
        // 如果开启了CARD_EXTRACT宏，则记录解析的条目
        CardExtractor::addCard (CardExtractor::CARD_TYPE_PARAM, Vstr[1]);
#endif
    }
    m_dbServiceFactory->get<IParameterService> ()->Initial (p);

    // SG::Utility::SGParameter P1= m_dbServiceFactory->get<ParameterService> ()->GetSolverParameter();
    // std::cout<<P1.PrettyPrintJsonString();
    return true;
}

bool BDFImporter::CheckLegalityLSEQ ()
{
    auto   lseqService = m_dbServiceFactory->get<ILSEQService> ();
    size_t allSize     = lseqService->Size ();
    std::set<std::pair<SG::DataStructure::Common::Id, SG::DataStructure::Common::Id>> keySet;
    for (size_t i = 0; i < allSize; i++)
    {
        SG::DataStructure::FEM::LSEQData lseq;
        lseqService->FindByIndex (i, lseq);
        std::pair<SG::DataStructure::Common::Id, SG::DataStructure::Common::Id> key (lseq.m_sId, lseq.m_DAREA);
        if (keySet.find (key) == keySet.end ())
        {
            keySet.insert (key);
        }
        else
        {
            SGError << "THE FOLLOWING NON-UNTOUE SID/EX(CITATION ID PAIRS HAVE,BEEN SPECTFTED IN ISEO BULK DATA ENTRTES";
            return false;
        }
    }
    return true;
}

bool BDFImporter::ParseExecutiveSystemParameter ()
{
    for (auto& singleLine : m_ExecutiveSystemParameterBlock)
    {
        std::size_t const blankIndex = singleLine.find_first_of (' ');

        std::string key     = singleLine.substr (0, blankIndex);
        std::string content = singleLine.substr (blankIndex + 1);
        boost::to_upper (key);

        FEM::Subcase::ControlInfo tempControlInfo;
        BDF::parseCaseControlLine (content, tempControlInfo);

        SG::Utility::SGParameter parameter;
        parameter.AddString ("KEY", tempControlInfo.m_Key);
        parameter.AddString ("VALUE", tempControlInfo.m_Vaule);

        if (tempControlInfo.m_vecKeys.size () > 0)
        {
            parameter.AddString ("I", tempControlInfo.m_vecKeys[0]);
        }
        m_dbServiceFactory->get<IParameterService> ()->AddExecutiveSystem (parameter);

#ifdef CARD_EXTRACT
        // 如果开启了CARD_EXTRACT宏，则记录解析的条目
        CardExtractor::addCard (CardExtractor::CARD_TYPE_PARAM, key + " " + tempControlInfo.m_Key);
#endif
    }

    return true;
}

bool BDFImporter::ParseCaseControl ()
{
    // 创建变量并初始化
    std::vector<std::vector<std::string>> allsubcase;  // 存储解析出的每个 SUBCASE 条目
    allsubcase.reserve (m_PostBlock.size ());          // 预留空间以提高效率

    std::vector<std::string> gloadSubcaseSet;          // 存储全局解析相关的条目（如 SOL）
    gloadSubcaseSet.reserve (m_PostBlock.size ());     // 预留空间以提高效率

    // 将 EntryInfo 分类为 SUBCASE 和其他条目
    ClassifyEntryInfo (allsubcase, gloadSubcaseSet);

    // 将解析后的 SUBCASE 存入数据库
    auto service = m_dbServiceFactory->get<ISubcaseService> ();

    // 初始化全局和临时 SubCase 对象
    SG::Utility::SGParameter All_subcase;
    SG::Utility::SGParameter global_subcase;
    global_subcase.AddString ("SUBCASE", "1");

    // 解析全局设置并应用到 global_subcase 中
    ParseSingleCaseControl (global_subcase, gloadSubcaseSet);

    // 解析所有的 SUBCASE 条目，并将其存储到数据库
    std::size_t const caseSize = allsubcase.size ();  // SUBCASE 条目的数量

    // 遍历所有 SUBCASE 条目进行解析
    for (std::size_t curCaseIndex = 0; curCaseIndex < caseSize; curCaseIndex++)
    {
        // 将全局设置应用到当前的 temp_subcase 中
        SG::Utility::SGParameter temp_subcase (global_subcase.Clone ());
        // 解析单个 SUBCASE
        ParseSingleCaseControl (temp_subcase, allsubcase[curCaseIndex]);
        bool isHaveSUBCASE = temp_subcase.Has ("SUBCASE");
        if (isHaveSUBCASE)
        {
            std::string caseID = temp_subcase["SUBCASE"]["MAIN_KEY"].GetString ();
            All_subcase.AddValue (caseID, temp_subcase);
        }
        else
        {
            SGError << "subcase donot have SUBCASE ID";
        }
    }

    // 如果没有 SUBCASE 条目，则只存储全局设置
    if (caseSize == 0)
    {
        All_subcase.AddValue ("1", global_subcase);
    }

    service->Initial (All_subcase);
    return true;  // 返回解析成功
}

void BDFImporter::ParseSingleCaseControl (SG::Utility::SGParameter& singleSubcase, std::vector<std::string>& singleSubcaseInfo)
{
    // 默认均为静力分析，在后续解析中会逐渐更改
    SG::Utility::SGParameter ParameterAnalysis;
    if (!singleSubcase.Has ("SOL"))
    {
        SG::Utility::SGParameter ParameterAnalysis;
        ParameterAnalysis.AddString ("MAIN_KEY", "101");
        singleSubcase.AddValue ("SOL", ParameterAnalysis);
    }

    // 遍历 singleSubcaseInfo 中的每个全局设置条目
    for (auto& singleLine : singleSubcaseInfo)
    {
        // 解析条目内容，并存储到全局解析结构体 s_ParserStruct 中
        try
        {
            boost::trim (singleLine);
            if (singleLine.empty ())
                continue;

            FEM::Subcase::ControlInfo tempControlInfo;

            BDF::parseCaseControlLine (singleLine, tempControlInfo);
            boost::to_upper (tempControlInfo.m_Key);
            auto funIter = BDF::CaseDataEntryParserFactory::GetInstance ()->GetFunction (tempControlInfo.m_Key);
            if (funIter != nullptr)
            {
                funIter (tempControlInfo, singleSubcase);
            }
            else
            {
                SGWarn << "[Function: ParseSingleCaseControl] Donot support " << tempControlInfo.m_Key;
            }

#ifdef CARD_EXTRACT
            // 如果开启了CARD_EXTRACT宏，则记录解析的条目
            CardExtractor::addCard (CardExtractor::CARD_TYPE_CONTROL, tempControlInfo.m_Key);
#endif
        }
        catch (const std::exception& e)
        {
            SGError << e.what () << '\n';
        }
    }

    // 屈曲分析引用的静力工况可能不存在（此时没有不存在STATSUB关键字，且整个文件只存在两个工况）
    bool isHaveAnalysisTypes = singleSubcase.Has ("SOL");

    if (isHaveAnalysisTypes)
    {
        std::string analysisType    = singleSubcase["SOL"]["MAIN_KEY"].GetString ();
        bool        isHaveStaticSub = singleSubcase.Has ("STATSUB");
        if (analysisType == "105" && (!isHaveStaticSub))
        {
            SG::Utility::SGParameter ParameterSTATSUB;
            ParameterSTATSUB.AddString ("MAIN_KEY", std::to_string (BDF::CaseDataEntryParserFactory::GetInstance ()->m_FirstSubcaseID));
            singleSubcase.AddValue ("STATSUB", ParameterSTATSUB);
        }
    }
    else
    {
        SGError << "SUBCASE donot have SOL";
    }
}

BDFImporter::IncludeState BDFImporter::ParseInclude (std::vector<std::string> folderStack)
{
    // 如果是include
    if (m_CompleteLineKey == "INCLUDE")
    {
        std::size_t const start = m_CompleteLine[0].find ('\'');

        // 如果没有找到单引号，则返回空字符串
        if (start == std::string::npos)
        {
            SGError << "GetIncludeFilePath:" << m_CompleteLine[0] << "can't find first ' ";
            return INCLUDE_FAIL;
        }

        // 查找第二个单引号的位置
        std::size_t const end = m_CompleteLine[0].find ('\'', start + 1);

        // 如果没有找到第二个单引号，则返回空字符串
        if (end == std::string::npos)
        {
            SGError << "GetIncludeFilePath:" << m_CompleteLine[0] << "can't find end ' ";
            return INCLUDE_FAIL;
        }

        std::string fileName = m_CompleteLine[0].substr (start + 1, end - start - 1);
        std::replace (fileName.begin (), fileName.end (), '\\', '/');

        // Search for the file in folder stack from top to bottom
        std::string foundFilePath;
        bool        fileFound = false;

        for (auto r_iter = folderStack.rbegin (); r_iter != folderStack.rend (); ++r_iter)
        {
            const std::string testPath = boost::filesystem::weakly_canonical (*r_iter + "/" + fileName).string ();
            if (boost::filesystem::exists (testPath))
            {
                foundFilePath = testPath;
                fileFound     = true;
                break;
            }
        }

        // If not found in any folder in stack, try with just the file name (current directory)
        if (!fileFound)
        {
            std::string testPath = boost::filesystem::weakly_canonical (fileName).string ();
            if (boost::filesystem::exists (testPath))
            {
                foundFilePath = testPath;
                fileFound     = true;
            }
        }

        if (!fileFound)
        {
            SGError << "can't find input file: " << fileName;
            return INCLUDE_FAIL;
        }

        // Extract folder path from found file path
        std::string includeFolder = boost::filesystem::path (foundFilePath).make_preferred ().parent_path ().string ();
        SGInfo << "Begin Import file : " << foundFilePath;
        std::ifstream includeFile (foundFilePath, ios::in);
        if (!includeFile.is_open ())
        {
            SGError << "can't open input file: " << foundFilePath << " \n";
            return INCLUDE_FAIL;
        }

        std::queue<std::string> linesQueue;  // 创建一个队列用于存储读取的行
        std::string             templine;
        while (std::getline (includeFile, templine))
        {
            linesQueue.push (templine);
        }
        // 关闭文件
        includeFile.close ();

        // Push the new folder to the stack for the included file
        folderStack.emplace_back (includeFolder);

        if (ParseFile (folderStack, linesQueue))
        {
            return INCLUDE_SUCCESS;
        }

        return INCLUDE_FAIL;
    }

    return NOT_INCLUDE;
}
void BDFImporter::GetNextLine (std::queue<string>& File, _OUT std::string& StrLine)
{
    StrLine = "";  // 清空当前行字符串，以准备存储新读取的行
    // 循环直到文件结束
    while (!File.empty ())
    {
        // 从文件中读取一行
        StrLine = File.front ().c_str ();
        File.pop ();

        // 查找注释符 '$' 的索引
        // to do未实现对$S700判断
        auto annoIndex = StrLine.find ('$');

        // 如果行以注释符开始，则继续读取下一行
        if (0 == annoIndex)
        {
            continue;
        }

        // 如果读取到空行，则继续读取下一行
        if (StrLine.empty () || StrLine == "\r" || StrLine == "\n" || StrLine == "\r\n")
        {
            continue;
        }

        // 如果中间出现 '$'，则截断字符串，保留注释符之前的内容
        if (annoIndex != std::string::npos)
        {
            StrLine = StrLine.substr (0, annoIndex);
        }

#ifdef __linux__
        // 如果在 Linux 下读取到以 '\r' 结尾的行，去掉 '\r'
        if ('\r' == StrLine.back ())
        {
            StrLine.pop_back ();
        }
#endif

        // 成功读取到有效行，退出循环
        break;
    }
}
void BDFImporter::GetCompleteLine (std::queue<string>& File, std::string& _OUT curLine)
{
    // 清空完整行容器，以准备存储新读取的行
    m_CompleteLine.clear ();

    // 将当前行添加到完整行容器中
    m_CompleteLine.push_back (curLine);

    // 将更新Completekey 移到GetCompleteLine中，方便对TAB类续行的操作
    UpdateCompleteLineKey (m_CompleteLine[0]);

    bool isendtEntry = false;  // 判断当前词条是否为endt词条
    bool isSet       = false;  // 判断当前词条是否为Set，该词条可能存在换行
    bool isInclude   = false;  // 判断当前词条是否为Set，该词条可能存在换行
    auto iter        = s_endtEntry.find (m_CompleteLineKey);
    if (iter != s_endtEntry.end ())
    {
        isendtEntry = true;
    }
    else if (boost::starts_with (boost::trim_left_copy ((boost::to_upper_copy (curLine))), "SET "))
    {
        isSet = true;
    }
    else if (boost::starts_with (boost::trim_left_copy ((boost::to_upper_copy (curLine))), "INCLUDE "))
    {
        curLine = boost::trim_copy (curLine);
        // if the line ends with a single quote it is a complete include statement
        isInclude = !boost::algorithm::ends_with (curLine, "'");
    }

    // 标志变量，用于判断是否继续读取行
    bool isContinue = true;
    curLine         = "";

    // 循环读取行，直到不再继续或文件结束
    while (isContinue && !File.empty ())
    {
        // 从文件中获取下一行
        GetNextLine (File, curLine);

        // 对于endt于非endt两种continue不一样
        if (isendtEntry)
        {
            // endt的下一行不是续行，之前都插入到m_CompleteLine中
            bool const isEnndt = SG::Import::BDFImporter::IsEndtContinue (curLine);
            m_CompleteLine.push_back (curLine);
            if (isEnndt)
            {
                isContinue = false;
                GetNextLine (File, curLine);
            }
        }
        else if (isSet)
        {
            // set 的下一行的第一个字只要是数字就继续是续行
            const std::string trimed = boost::trim_left_copy (curLine);
            if (!boost::empty (trimed) && std::isdigit (static_cast<unsigned char> (trimed[0])) != 0)
            {
                isContinue = true;
                m_CompleteLine.push_back (curLine);
            }
            else
            {
                isContinue = false;
            }
        }
        else if (isInclude)
        {
            // 如果没有找到结束的"'"，则继续读取下一行
            const std::string trimed = boost::trim_copy (curLine);
            m_CompleteLine[0] += trimed;
            isContinue = !boost::algorithm::ends_with (trimed, "'");
        }
        else
        {
            // 判断是否继续读取，依据是当前行的内容
            isContinue = SG::Import::BDFImporter::IsContinue (curLine);
            // 如果继续，添加当前行到完整行容器中
            if (isContinue)
            {
                m_CompleteLine.push_back (curLine);
            }
        }
    }
}

bool BDFImporter::IsEndtContinue (std::string& str)
{
    if (str.empty ())
        return false;

    // 找到最后一个非空字符
    size_t lastNonSpacePos = str.find_last_not_of (" \t\n\r\f\v");

    // 是不是全是空格
    if (lastNonSpacePos == std::string::npos)
        return false;

    // 字串对比
    if (lastNonSpacePos >= 3)
    {
        std::string subStr = str.substr (lastNonSpacePos - 3, 4);
        boost::to_upper (subStr);
        if (subStr == "ENDT")
        {
            return true;
        }
    }
    return false;
}

bool BDFImporter::IsContinue (std::string& str)
{
    // 第一个字符为’*’或者‘+’，或者前8个字符中第一个非‘ ’（空格）开头的字符为‘,’或全是空格。
    // 检查字符串的第一个字符是否为 '+'、',' 或 '*'，以决定是否继续
    switch (str[0])
    {
    case '+':
    case ',':
    case '*':
        return true;   // 如果第一个字符是这些符号，返回 true
    case ' ':
        break;         // 如果第一个字符是空格，继续检查后续字符
    default:
        return false;  // 其他字符则返回 false
    }

    // 检查字符串的前8个字符中第一个非空格字符
    for (int i = 1; i < 8; i++)
    {
        if (' ' == str[i])
        {
            continue;  // 如果当前字符是空格，继续下一轮
        }

        if (',' == str[i])
        {
            return true;  // 如果找到逗号，返回 true
        }

        return false;     // 找到其他字符，返回 false
    }

    return true;          // 如果前8个字符全是空格，则返回 true
}

bool BDFImporter::IsBulkDataLine ()
{
    // control 的PARAM格式和自由模式的bulk的一致，直接返回true
    // output比较特殊，find （）
    // 其余同名的都可以寻找=
    if (m_CompleteLineKey == "OUTPUT")
    {
        std::size_t const bracketPos = m_CompleteLine[0].find ('(');
        if (bracketPos != std::string::npos)
        {
            return false;
        }
    }
    else if (m_CompleteLineKey == "SET")
    {
        return true;
    }
    else
    {
        std::size_t const equalPos = m_CompleteLine[0].find ('=');
        if (equalPos != std::string::npos)
        {
            return false;
        }
    }

    return true;
}

void BDFImporter::UpdateCompleteLineKey (std::string& line)
{
    m_CompleteLineKey = line.substr (0, 8);

    // 处理自由格式
    std::size_t const commaPos = m_CompleteLineKey.find (',');
    if (commaPos != std::string::npos)
    {
        // 截取逗号之前的部分
        m_CompleteLineKey = m_CompleteLineKey.substr (0, commaPos);
    }

    // 去除尾空格
    boost::trim_right (m_CompleteLineKey);
    boost::to_upper (m_CompleteLineKey);  // 将小写转化为大写
    // 处理长格式
    if (m_CompleteLineKey.back () == '*')
    {
        m_CompleteLineKey.pop_back ();
    }
    // 处理SET
    else if (boost::starts_with (boost::trim_left_copy (m_CompleteLineKey), "SET "))
    {
        m_CompleteLineKey = "SET";
    }
}

void BDFImporter::UpdateControlKey (std::string& controlLine)
{
    // 查找空格和等号的位置，选择最小的一个作为分隔符
    boost::trim (controlLine);
    std::size_t const blankIndex   = controlLine.find_first_of (' ');
    std::size_t const equalIndex   = controlLine.find_first_of ('=');
    std::size_t const bracketIndex = controlLine.find_first_of ('(');
    boost::to_upper (controlLine);

    // 比较三个索引的最小值
    std::size_t const min_val = std::min ({ blankIndex == std::string::npos ? std::string::npos : blankIndex,
                                            equalIndex == std::string::npos ? std::string::npos : equalIndex,
                                            bracketIndex == std::string::npos ? std::string::npos : bracketIndex });

    m_ControlKey = controlLine.substr (0, min_val);
}

void BDFImporter::ClassifyEntryInfo (std::vector<std::vector<std::string>>& allsubcase, std::vector<std::string>& gloadSubcaseSet)
{
    std::vector<std::string> otherLines;
    otherLines.reserve (m_PostBlock.size ());
    // 循环遍历 EntryInfo 中的每一行字符串
    for (std::size_t i = 0; i < m_PostBlock.size (); i++)
    {
        // 更新当前行的关键字到m_m_ControlKey，
        UpdateControlKey (m_PostBlock[i]);

        // 如果关键字为 "SUBCASE"
        if (m_ControlKey == "SUBCASE")
        {
            std::vector<std::string> subcase;
            while (true)
            {
                subcase.push_back (m_PostBlock[i]);
                i++;

                // 遍历完 EntryInfo 或遇到下一个 SUBCASE/BEGIN BULK 停止收集
                if (i == m_PostBlock.size ())
                {
                    break;
                }
                if (boost::icontains (m_PostBlock[i], "SUBCASE"))
                {
                    break;
                }
                if (boost::icontains (m_PostBlock[i], "BEGIN BULK"))
                {
                    break;
                }
            }
            i--;                             // 回到上一个 i，避免多跳一行
            allsubcase.push_back (subcase);  // 将收集到的 SUBCASE 行存入 allsubcase
        }
        else
        {
            // 检查关键字是否在解析字典中
            auto funIter = BDF::CaseDataEntryParserFactory::GetInstance ()->GetFunction (m_ControlKey);
            if (funIter != nullptr)
            {
                // 如果关键字存在于解析字典中，则将其作为全局解析设置
                gloadSubcaseSet.push_back (m_PostBlock[i]);
            }
            else
            {
                // 其他非 SUBCASE 和全局设置的行，存入 otherLine
                otherLines.push_back (m_PostBlock[i]);
            }
        }
    }
    // 将 EntryInfo 与 otherLine 交换，otherLine 成为未分类的部分
    m_PostBlock.swap (otherLines);
}
